#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "rtk_api_ext.h"
#include <libmdionetlink/mdio_api.h>

char *bus="stmmac-1";
uint16_t gdev = 0x18;

int32 g9x_eth1_read_phy_reg(uint8 phyID, uint8 regAddr, uint16 *data)
{
	return mdio_read_reg(bus, phyID, regAddr, data);
}

int32 g9x_eth1_write_phy_reg(uint8 phyID, uint8 regAddr, uint16 data)
{
	return mdio_write_reg(bus, phyID, regAddr, data);
}

int checkCPU()
{
    union w {
        int  a;
        char b;
    } c;
    c.a = 1;
    /* ==1, is little ending 
     * ==0, is Big ending 
     * */
    return (c.b == 1);
}

int main(int argc, char **argv)
{
	uint32_t chipID,chipFwVer;
	rtk_api_ret_t ret = RT_ERR_OK;
	uint8 portid;
	
	if (mdio_init()) {
		if (mdio_modprobe()) {
			fprintf(stderr, "ERROR: mdio-netlink module not "
				"detected, and could not be loaded.\n");
			return 1;
		}

		if (mdio_init()) {
			fprintf(stderr, "ERROR: Unable to initialize.\n");
			return 1;
		}
	}

	RTL9040_MDCMDIO_init(g9x_eth1_write_phy_reg, g9x_eth1_read_phy_reg);

	/*ret = rtk_getCHIPID(&chipID);
	if(ret == RT_ERR_OK){
		printf("chipID: 0x%4.4x\n", chipID);
	}else{
		printf("rtk_getCHIPID return: %d\n", ret);
	}*/
	
   if(argc == 1){
		printf("\trtl904xCtrl acceptsleeprequest {portmask} to enable accpet sleep request capability on portmask\n");
		printf("\trtl904xCtrl defaultvlan to configure rtl904x for all ports in single default vlan\n");
		printf("\trtl904xCtrl disablerwake {0-4} to disable remote wakeup dection on port\n");
		printf("\trtl904xCtrl disablewholechipsleep to disable whole chip sleep on this switch chip\n");
		printf("\trtl904xCtrl emclp to configure rtl904x as emc test partner\n");
		printf("\trtl904xCtrl emcdut to configure rtl904x as device under test\n");
		printf("\trtl904xCtrl enablerwake {0-4} to enable remote wakeup dection on port\n");
		printf("\trtl904xCtrl enablewholechipsleep to enable whole chip sleep on this switch chip\n");
		printf("\trtl904xCtrl eraseall to erase spi flash\n");
		printf("\trtl904xCtrl forwardrwake {0-4} {portmask} to assign forward rwake portmask for speical port\n");
		printf("\trtl904xCtrl forwardsleeprequest {portmask} to forward sleep request capability on portmask\n");
		printf("\trtl904xCtrl getfwver to get firmware version\n");
		printf("\trtl904xCtrl getphystatus to get port0~5 phy status\n");
		printf("\trtl904xCtrl getportvlancfg to get port vlan config\n");
		/*printf("\trtl904xCtrl getportstat to get port statistics\n");
		printf("\trtl904xCtrl globalstat {reset|start|stop} to reset, start or stop stat global control\n");
		printf("\trtl904xCtrl phypktgen {0-4} {enable|disable} to enable or disable pktgen feature\n");
		printf("\trtl904xCtrl phypktgen {0-4} clearcounter to clear pktgen counter\n");
		printf("\trtl904xCtrl phypktgen {0-4} resettxrx to reset pktgen txrx\n");
		printf("\trtl904xCtrl phypktgen {0-4} txnumber {NUMBER} to set pktgen txnumber\n");*/
		printf("\trtl904xCtrl phyrole {0-4} {master|slave} to config the 100bast-t1 phy role as master or slave\n");
		printf("\trtl904xCtrl phyreset {0-4} to do phy reset\n");
		printf("\trtl904xCtrl portlocalstate {0-4} to get port's local state\n");
		/*printf("\trtl904xCtrl portstat {0-7} {reset|start|stop} to reset, start or stop stat port control\n");*/
		printf("\trtl904xCtrl sendrwake {portmask} to send rwake on portmask\n");
		printf("\trtl904xCtrl sendsleeprequest {portmask} to send sleeprequest on portmask\n");
		printf("\trtl904xCtrl singletest to configure rtl904x for single test\n");
		printf("\trtl904xCtrl sleeprequestandwurcap {portmask} to enable the capability of sleeprequest and WUR on portmask\n");
		printf("\trtl904xCtrl state to show global state\n");
		printf("\trtl904xCtrl transmitrwakecap {portmask} to enable transmit rwake capbility on portmake\n");
		printf("\trtl904xCtrl updatefw to update firmware into rtl904x\n");
		printf("\trtl904xCtrl wakeISRclearall to clear all ports wake ISR state\n");
		printf("\trtl904xCtrl wholechipreset to set global state as ST_RESET\n");
		printf("\trtl904xCtrl wholechipsleep to set global state as ST_WHOLE_CHIP_SLEEP\n");
		printf("\trtl904xCtrl wholechipsleepmask {portmask} to set portmask which can cause wholechipsleep\n");
	}else if(argc == 2){
		if(memcmp(argv[1],"defaultvlan",strlen("defaultvlan")) == 0){     
			printf("will configure rtl904x for all ports in single default vlan\n");
 			dfsgw_904x_single_default_vlan_config();
		}else if(memcmp(argv[1],"disablewholechipsleep",strlen("disablewholechipsleep")) == 0){
			printf("will do rtl9040_op_WholechipSleepmskEnable_set(DISABLED)\n");
 			rtl9040_op_WholechipSleepmskEnable_set(DISABLED);
		}else if(memcmp(argv[1],"emclp",strlen("emclp")) == 0){
			printf("will configure rtl904x as emc test partner\n");
			dfsgw_904x_emc_test_partner_config();
		}else if(memcmp(argv[1],"emcdut",strlen("emcdut")) == 0){
			printf("will configure rtl904x as device under test\n");
			dfsgw_904x_emc_test_dut_config();
		}else if(memcmp(argv[1],"enablewholechipsleep",strlen("enablewholechipsleep")) == 0){
			printf("will do rtl9040_op_WholechipSleepmskEnable_set(ENABLED)\n");
 			rtl9040_op_WholechipSleepmskEnable_set(ENABLED);
		}else if(memcmp(argv[1],"eraseall",strlen("eraseall")) == 0){
			printf("will do rtk_spiflash_eraseall\n");
 			rtk_spiflash_eraseall();
		}else if(memcmp(argv[1],"getfwver",strlen("getfwver")) == 0){
 			dfsgw_904x_get_fw_ver();
		}else if(memcmp(argv[1],"getphystatus",strlen("getphystatus")) == 0){
 			dfsgw_904x_get_phy_status();
		}/*else if(memcmp(argv[1],"getportstat",strlen("getportstat")) == 0){
			dfsgw_904x_get_port_stat();
		}*/else if(memcmp(argv[1],"getportvlancfg",strlen("getportvlancfg")) == 0){
			dfsgw_904x_get_port_vlan_cfg();
		}else if(memcmp(argv[1],"singletest",strlen("singletest")) == 0){
			printf("will configure rtl904x for single test\n");
 			dfsgw_904x_single_test_config();
		}else if(memcmp(argv[1],"state",strlen("state")) == 0){
			uint16 state;
 			rtl9040_op_state_status_get(&state);
 			printf("rtl9040_op_state_status_get state:0x%x\n", state);
		}else if(memcmp(argv[1],"updatefw",strlen("updatefw")) == 0){
			printf("will update firmware \"fw_config.bin\" into rtl904x\n");
 			dfsgw_904x_fw_update("/lib/firmware/fw_config.bin");
		}else if(memcmp(argv[1],"wakeISRclearall",strlen("wakeISRclearall")) == 0){
			ret = rtl9040_op_port_wakeISR_clearall();
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_port_wakeISR_clearall ok!\n");
			}
		}else if(memcmp(argv[1],"wholechipreset",strlen("wholechipreset")) == 0){
			ret = rtl9040_op_state_set(0x10);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_state_set for OP_ST_RESET ok!\n");
			}
		}else if(memcmp(argv[1],"wholechipsleep",strlen("wholechipsleep")) == 0){
			ret = rtl9040_op_state_set(0x40);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_state_set for OP_ST_WHOLE_CHIP_SLEEP ok!\n");
			}
		}
	}else if(argc == 3){
		if(memcmp(argv[1],"acceptsleeprequest",strlen("acceptsleeprequest")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_port_AccpetSleepRequest_cap_set(portmask);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_port_AccpetSleepRequest_cap_set for portmask %x ok!\n", portmask);
			}
		}else if(memcmp(argv[1],"disablerwake",strlen("disablerwake")) == 0){
			int portid;
			uint8 portmask=0;
			uint8 disablemask;
			sscanf(argv[2], "%d", &portid);
			if(portid < 0 || portid > 4){
				printf("please input correct portid 0~4\n");
				return 1;
			}
			portmask |= (1<<portid);
			ret = rtl9040_op_disable_rwake_get(&disablemask);
			if(ret != RT_ERR_OK){
				printf("rtl9040_op_disable_rwake_get failed!\n");
				return 1;
			}
			if(disablemask & portmask){
				printf("port %d already rwake disabled!\n", portid);
			}else{
				disablemask |= portmask;
				ret = rtl9040_op_disable_rwake_set(disablemask);
				if(ret == RT_ERR_OK){
					printf("disablerwake for port %d ok!\n", portid);
				}
			}

		}else if(memcmp(argv[1],"enablerwake",strlen("enablerwake")) == 0){
			int portid;
			uint8 portmask=0;
			uint8 disablemask;
			sscanf(argv[2], "%d", &portid);
			if(portid < 0 || portid > 4){
				printf("please input correct portid 0~4\n");
				return 1;
			}
			portmask |= (1<<portid);
			ret = rtl9040_op_disable_rwake_get(&disablemask);
			if(ret != RT_ERR_OK){
				printf("rtl9040_op_disable_rwake_get failed!\n");
				return 1;
			}
			if((disablemask & portmask) == 0){
				printf("port %d already rwake enabled!\n", portid);
			}else{
				disablemask &= (~portmask);
				ret = rtl9040_op_disable_rwake_set(disablemask);
				if(ret == RT_ERR_OK){
					printf("enablerwake for port %d ok!\n", portid);
				}
			}
		}else if(memcmp(argv[1],"forwardsleeprequest",strlen("forwardsleeprequest")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_port_TXforwardSleepcmd_mask_set(portmask);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_port_TXforwardSleepcmd_mask_set for portmask %x ok!\n", portmask);
			}
		}
		/*else if(memcmp(argv[1],"globalstat",strlen("globalstat")) == 0){
			if(memcmp(argv[2],"reset",strlen("reset")) == 0){
				printf("will call rtk_stat_global_reset\n");
				rtk_stat_global_reset();
			}else if(memcmp(argv[2],"start",strlen("start")) == 0){
				printf("will call rtk_stat_global_start\n");
				rtk_stat_global_start();
			}else if(memcmp(argv[2],"stop",strlen("stop")) == 0){
				printf("will call rtk_stat_global_stop\n");
				rtk_stat_global_stop();
			}
		}*/
		else if(memcmp(argv[1],"phyreset",strlen("phyreset")) == 0){
			int phyid;
			uint8 phymask=0;
			sscanf(argv[2], "%d", &phyid);
			if(phyid < 0 || phyid > 4){
				printf("please input correct phyid 0~4\n");
				return 1;
			}
			phymask |= (1<<phyid);
			ret = phy_reset(phymask);
			if(ret == RT_ERR_OK){
				printf("phyreset for phyid %d ok!\n", phyid);
			}
		}else if(memcmp(argv[1],"portlocalstate",strlen("portlocalstate")) == 0){
			int portid;
			sscanf(argv[2], "%d", &portid);
			if(portid < 0 || portid > 4){
				printf("please input correct portid 0~4\n");
				return 1;
			}
			dfsgw_904x_get_port_state(portid);
		}else if(memcmp(argv[1],"sendrwake",strlen("sendrwake")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_sendrwake(portmask);
			if(ret == RT_ERR_OK){
				printf("sendrwake on portmask 0x%x ok!\n", portmask);
			}
		}else if(memcmp(argv[1],"sendsleeprequest",strlen("sendsleeprequest")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_port_send_SleepRequest(portmask);
			if(ret == RT_ERR_OK){
				printf("sendsleeprequest on portmask 0x%x ok!\n", portmask);
			}
		}else if(memcmp(argv[1],"sleeprequestandwurcap",strlen("sleeprequestandwurcap")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_port_SleepReqCap_and_WURcap_set(portmask);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_port_SleepReqCap_and_WURcap_set on portmask 0x%x ok!\n", portmask);
			}
		}else if(memcmp(argv[1],"transmitrwakecap",strlen("transmitrwakecap")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_transmit_rwake_cap_set(portmask);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_transmit_rwake_cap_set on portmask 0x%x ok!\n", portmask);
			}
		}
		else if(memcmp(argv[1],"wholechipsleepmask",strlen("wholechipsleepmask")) == 0){
			int portmask;
			sscanf(argv[2], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			ret = rtl9040_op_port_WholechipSleepmsk_set(portmask);
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_port_WholechipSleepmsk_set on portmask 0x%x ok!\n", portmask);
			}
		}
	}else if(argc == 4){
		if(memcmp(argv[1],"forwardrwake",strlen("forwardrwake")) == 0){
			int portid;
			int portmask;

			sscanf(argv[2], "%d", &portid);
			if(portid < 0 || portid > 4){
				printf("please input correct portid 0~4\n");
				return 1;
			}
			sscanf(argv[3], "%x", &portmask);
			if(portmask & 0xE0 ){
				printf("portmask should only mask bit0~bit4\n");
				return 1;
			}
			switch(portid){
				case 0:
					ret = rtl9040_op_rwake_forward_p0Cfg_set(portmask);
					break;
				case 1:
					ret = rtl9040_op_rwake_forward_p1Cfg_set(portmask);
					break;
				case 2:
					ret = rtl9040_op_rwake_forward_p2Cfg_set(portmask);
					break;
				case 3:
					ret = rtl9040_op_rwake_forward_p3Cfg_set(portmask);
					break;
				case 4:
					ret = rtl9040_op_rwake_forward_p4Cfg_set(portmask);
					break;
				default:
					printf("please input correct portid 0~4\n");
					return 1;
			}
			if(ret == RT_ERR_OK){
				printf("rtl9040_op_rwake_forward_p%dCfg_set(0x%x) ok!\n", portid, portmask);
			}
		}
		/*else if(memcmp(argv[1],"phypktgen",strlen("phypktgen")) == 0){
			int phyid;
			rtk_enable_t enable;
			sscanf(argv[2], "%d", &phyid);
			if(phyid < 0 || phyid > 4){
				printf("please input correct phyid 0~4\n");
				return 1;
			}
			if(memcmp(argv[3],"enable",strlen("enable")) == 0){
				enable = ENABLED;
				phy_pktgen_enable_set(phyid, enable);
			}else if(memcmp(argv[3],"disable",strlen("disable")) == 0){
				enable = DISABLED;
				phy_pktgen_enable_set(phyid, enable);
			}else if(memcmp(argv[3],"clearcounter",strlen("clearcounter")) == 0){
				phy_pktgen_clearcounter(phyid);
			}else if(memcmp(argv[3],"resettxrx",strlen("resettxrx")) == 0){
				phy_pktgen_resettxrx(phyid);
			}else{
				printf("please input enable or disable for phypktgen:%d\n", phyid);
				return 1;
			}
		}else if(memcmp(argv[1],"portstat",strlen("portstat")) == 0){
			int port;
			sscanf(argv[2], "%d", &port);
			if(port < 0 || port > 7){
				printf("please input correct port 0~7\n");
				return 1;
			}
			if(memcmp(argv[3],"reset",strlen("reset")) == 0){
				printf("will call rtk_stat_port_reset(%d)\n", port);
				rtk_stat_port_reset(port);
			}else if(memcmp(argv[3],"start",strlen("start")) == 0){
				printf("will call rtk_stat_port_start(%d)\n", port);
				rtk_stat_port_start(port);
			}else if(memcmp(argv[3],"stop",strlen("stop")) == 0){
				printf("will call rtk_stat_port_stop(%d)\n", port);
				rtk_stat_port_stop(port);
			}
		}*/ else if(memcmp(argv[1],"phyrole",strlen("phyrole")) == 0){
			int phyid;
			uint8 phymask=0;
			sscanf(argv[2], "%d", &phyid);
			if(phyid < 0 || phyid > 4){
				printf("please input correct phyid 0~4\n");
				return 1;
			}
			phymask |= (1<<phyid);
			if(memcmp(argv[3],"master",strlen("master")) == 0){
				printf("will config phyid:%d role as master\n", phyid);
				phy_rolecfg_set(phymask, 1);
				/*phy_reset(phymask); //should use phyreset subcommand*/

			}else if(memcmp(argv[3],"slave",strlen("slave")) == 0){
				printf("will config phyid:%d role as slave\n", phyid);
				phy_rolecfg_set(phymask, 0);
				/*phy_reset(phymask); //should use phyreset subcommand*/
			}
		}
	}else if(argc == 5){
		/*if(memcmp(argv[1],"phypktgen",strlen("phypktgen")) == 0){
			int phyid;
			uint32 number;
			sscanf(argv[2], "%d", &phyid);
			if(phyid < 0 || phyid > 4){
				printf("please input correct phyid 0~4\n");
				return 1;
			}
			if(memcmp(argv[3],"txnumber",strlen("txnumber")) == 0){
				sscanf(argv[4], "%d", &number);
				phy_pktgen_txnumber_set(phyid, number);
			}
		}*/
	}
}

int dfsgw_904x_get_fw_ver()
{
	uint32_t chipFwVer;
	RTL9040_REGISTER_GET(0x5A004C, &chipFwVer);
	printf("%4.4x\n", chipFwVer);
}

int dfsgw_904x_get_phy_status()
{
	rtk_api_ret_t retVal;
    uint8 phyid;
    uint8 isMaster;
    uint8 rdlinkok;
    rtk_enable_t outputlinkst;
    uint32 number,counter,correctrxcounter,errorrxcounter;

	printf("%5s %6s %4s %12s %8s %8s %8s\n", "PhyId","Role", "Link", "OutputLinkSt","TxCnt", "CorRx", "ErrRx");
    for(phyid = 0; phyid < 5; phyid++){
    	retVal = phy_rolecfg_get(phyid, &isMaster);
    	if(retVal != RT_ERR_OK){
    		printf("phy_rolecfg_get phyid %d ret %d\n", phyid, retVal);
    		continue;   		
    	}
    	retVal = phy_linkst_get(phyid, &rdlinkok);
    	if(retVal != RT_ERR_OK){
    		printf("phy_linkst_get phyid %d ret %d\n", phyid, retVal);
    		continue;
		}
		retVal = phy_pktgen_txcounter_get(phyid, &counter);
		if(retVal != RT_ERR_OK){
			printf("phy_pktgen_txcounter_get phyid %d ret %d\n", phyid, retVal);
			continue;
		}
		/*phy_pktgen_txnumber_get(phyid, &number);*/
		phy_outputlinkst_get(phyid, &outputlinkst);
		phy_pktgen_correctrxcounter_get(phyid, &correctrxcounter);
		phy_pktgen_errorrxcounter_get(phyid, &errorrxcounter);
		printf("%5d %6s %4s %12s %8d %8d %8d\n", phyid,
			isMaster?"master":"slave",
			rdlinkok?"up":"down",
			outputlinkst?"enabled": "disabled",
			counter, correctrxcounter, errorrxcounter);
	}
}

int dfsgw_904x_get_port_stat()
{
	rtk_api_ret_t retVal;
	rtk_port_t port;
	rtk_stat_port_type_t statIdxArray[5] = {STAT_IfInOctets, STAT_IfInUcastPkts, STAT_IfOutOctets, STAT_IfOutUcastPkts, STAT_IfOutBroadcastPkts};
	rtk_stat_port_type_t statIdx;
	rtk_stat_counter_t IfInOctets,IfInUcastPkts,IfOutOctets,IfOutUcastPkts,OutBroadcastPkts;

	printf("%4s %11s %11s %11s %12s %12s\n", "Port", "IfInOctets","InUcastPkts", "IfOutOctets", "OutUcastPkts", "OutBcastPkts");
	for(port = 0; port < 7; port++){
		statIdx = STAT_IfInOctets;
		rtk_stat_port_get(port, STAT_IfInOctets, &IfInOctets);
		rtk_stat_port_get(port, STAT_IfInUcastPkts, &IfInUcastPkts);
		rtk_stat_port_get(port, STAT_IfOutOctets, &IfOutOctets);
		rtk_stat_port_get(port, STAT_IfOutUcastPkts, &IfOutUcastPkts);
		rtk_stat_port_get(port, STAT_IfOutBroadcastPkts, &IfOutUcastPkts);
		printf("%4d %11lld %11lld %11lld %12lld %12lld\n", port,
			IfInOctets, IfInUcastPkts,
			IfOutOctets, IfOutUcastPkts, OutBroadcastPkts);
	}
}

char *acceptFrameTypeStr[5] = {"all", "tag_only", "untag_only", "none", "end"};
char *stpStateStr[5] = {"discarding", "blocking", "learning", "forwarding", "end"};
int dfsgw_904x_get_port_vlan_cfg()
{
	rtk_port_t port;
	rtk_vlan_t pvid;
	rtk_pri_t priority;
	rtk_portmask_t mbrmsk;
    rtk_portmask_t untagmsk;
    rtk_fid_t fid;
    rtk_vlan_ivlsvl_t ulfid;
    rtk_vlan_fwdmode_t vbfwd;
	rtk_vlan_acceptFrameType_t accept_frame_type;
	rtk_vlan_txTagStatus_t tag_status;
	rtk_enable_t igr_filter,egr_filter, tag_aware;
	rtk_stp_state_t stp_state;

	printf("%4s %4s %4s %15s %12s %9s %9s %10s\n", "Port","Pvid", "Fid", "AcceptFrameType", "EgrTagStatus", "IgrFilter", "EgrFilter", "StpState");
	for(port = 0; port < 7; port++){
		rtk_vlan_portPvid_get(port, &pvid, &priority);
		rtk_vlan_get(pvid, &mbrmsk, &untagmsk, &fid, &ulfid, &vbfwd);
		rtk_vlan_portAcceptFrameType_get(port, &accept_frame_type);
		rtk_vlan_portEgressTagStatus_get(port, &tag_status);
		rtk_vlan_portIgrFilterEnable_get(port, &igr_filter);
		rtk_vlan_portEgrFilterEnable_get(port, &egr_filter);
		rtk_vlan_tagAware_get(port, &tag_aware);
		if (fid > 14) {
			continue;
		}else{
        	rtk_stp_mstpState_get(fid, port, &stp_state);
		}
		printf("%4d %4d %4d %15s %12s %9s %9s %10s\n", port, pvid, fid,
			acceptFrameTypeStr[accept_frame_type], 
			tag_status?"without_tag":"with_tag", 
			igr_filter?"enable":"disable", 
			egr_filter?"enable":"disable",
			stpStateStr[stp_state]);
	}

}

rtk_api_ret_t dfsgw_904x_get_port_state(int portid)
{
	uint16 state;
	uint8 SleepReqCap_and_WURcap,AccpetSleepRequest_cap,TXforwardSleepcmd_cap,wakeByRemoteWakeUpPulse_flag,wakeByRemoteWakeUpRequest_flag;

	if(portid < 0 || portid > 4){
		return 1;
	}
	rtl9040_op_statelocal_status_get(portid, &state);
	rtl9040_op_port_SleepReqCap_and_WURcap_get(portid, &SleepReqCap_and_WURcap);
	rtl9040_op_port_AccpetSleepRequest_cap_get(portid, &AccpetSleepRequest_cap);
	rtl9040_op_port_TXforwardSleepcmd_cap_get(portid, &TXforwardSleepcmd_cap);
	rtl9040_op_port_wakeByRemoteWakeUpPulse_flag_get(portid, &wakeByRemoteWakeUpPulse_flag);
	rtl9040_op_port_wakeByRemoteWakeUpRequest_flag_get(portid, &wakeByRemoteWakeUpRequest_flag);
	printf("port: %d \n", portid);
	printf("localState: 0x%x \n", state);
	printf("SleepReqCap_and_WURcap: %s\n", SleepReqCap_and_WURcap?"on":"off");
	printf("AccpetSleepRequest_cap: %s\n", AccpetSleepRequest_cap?"on":"off");
	printf("TXforwardSleepcmd_cap: %s\n", TXforwardSleepcmd_cap?"on":"off");
	printf("WakeByRemoteWakeUpPulse_flag: %s\n", wakeByRemoteWakeUpPulse_flag?"on":"off");
	printf("WakeByRemoteWakeUpRequest_flag: %s\n", wakeByRemoteWakeUpRequest_flag?"on":"off");

	return RT_ERR_OK;
}
int dfsgw_904x_single_default_vlan_config()
{
	rtk_api_ret_t retVal;
	rtk_port_t port;
    rtk_portmask_t mbrmsk;
    rtk_portmask_t untagmsk;
    rtk_vlan_t vid;
    rtk_fid_t fid;
    rtk_vlan_ivlsvl_t ulfid = VLAN_IVL;
    rtk_vlan_fwdmode_t vbfwd = ALE_BASED_FWD;
    rtk_pri_t priority = 0;
    rtk_vlan_acceptFrameType_t accept_frame_type = ACCEPT_FRAME_TYPE_ALL;
    rtk_vlan_txTagStatus_t tag_status = TAG_STATUS_WITHOUT_TAG;
	rtk_enable_t stpAbility = ENABLED;
    rtk_stp_type_t stpType = STP_TYPE_RSTP;

	/*initialize VLAN*/
	rtk_vlan_init();
	rtk_stp_ability_set(stpAbility);
	rtk_stp_type_set(stpType);
	/*all the ports are in the default vlan 1 after VLAN is initialized.*/
	vid = 1;
	
	mbrmsk.bits[0] = 0x7f; /*port0~port6*/
	untagmsk.bits[0] = 0x7f;
	for(port = 0; port < 7; port++){
		rtk_vlan_portPvid_set(port, vid, priority);
		rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
		rtk_vlan_portEgressTagStatus_set(port, tag_status);
	}
}

void dfsgw_904x_fw_update(uint8* fileName)
{
    FILE  *fp = NULL;
    int32  len = 0;
    uint8  buf[256];
    uint32 addr = 0;
    /*when update flash firmware, stop cpu first to avoid cpu from executing
     *code which is updated */
    rtk_cpu_stop();
    /*erase whole flash to update new data*/
    rtk_spiflash_eraseall();
    /*open fw file and seek file pointer to head*/
    fp = fopen(fileName, "rb");
    if(fp == NULL)
	{
		printf("FILE %s open fail!\n", fileName);
		return -1;
	}
    fseek(fp, 0, SEEK_SET);
    /*add is pointer of flash, the fw is programmed from address #0 in flash*/
    addr = 0;
    /*start to read fw file and write to spi flash*/
    while(1) {
        /*read 256 byte from fw file*/
        len = fread(buf, sizeof(char), 256, fp);
        if (len == 0) {
            break;
        }
        /*program data whose length is len to flash*/
        rtk_spiflash_program(addr, len, buf);
        /*increase flash address for next programming*/
        addr += len;
        if (len < 256) {
            /*last data*/
            break;
        }
    }
    /*reset 8051 to load new firmware*/
    rtk_cpu_mem_reset();
}

int dfsgw_904x_single_test_config()
{
	rtk_api_ret_t retVal;
	rtk_port_t port;
	rtk_vlan_t vid1,vid2,vid3;
    rtk_portmask_t mbrmsk;
    rtk_portmask_t untagmsk;
    rtk_fid_t fid = 0;
    rtk_vlan_ivlsvl_t ulfid = VLAN_IVL;
    rtk_vlan_fwdmode_t vbfwd = ALE_BASED_FWD;
    rtk_pri_t priority = 0;
    rtk_vlan_acceptFrameType_t accept_frame_type = ACCEPT_FRAME_TYPE_ALL;
    rtk_vlan_txTagStatus_t tag_status = TAG_STATUS_WITHOUT_TAG;
    uint8 phymask;
    uint8 phyid;
    uint8 isMaster;
    rtk_enable_t stpAbility = ENABLED;
    rtk_stp_type_t stpType = STP_TYPE_RSTP;

    /*set p0,p2 phy as master*/
    phymask = 0x05;
    phy_rolecfg_set(phymask, 1);
    /*set p1,p3 phy as slave*/
    phymask = 0x0a;
    phy_rolecfg_set(phymask, 0);
    phy_reset(0x01);
    phy_reset(0x02);
    phy_reset(0x04);
    phy_reset(0x08);
 
	/*initialize VLAN*/
	rtk_vlan_init();
	/*rtk_stp_ability_set(stpAbility);
	rtk_stp_type_set(stpType);*/
	/*all the ports are in the default vlan 1 after VLAN is initialized.
	Modify it as follows:
	VLAN1 member:port0, port6[E1];
	VLAN2 member:port1, port2;
	VLAN3 member:port3, port5[E0];
	*/
	vid1 = 10;
	vid2 = 20;
	vid3 = 30;
	
	mbrmsk.bits[0] = 0x41; /*port0, port6*/
	untagmsk.bits[0] = 0x41;
	fid = 1;
	rtk_vlan_set(vid1, mbrmsk, untagmsk, fid, ulfid, vbfwd);

	mbrmsk.bits[0] = 0x06; /*port1, port2*/
	untagmsk.bits[0] = 0x06;
	fid = 2;
	rtk_vlan_set(vid2, mbrmsk, untagmsk, fid, ulfid, vbfwd);
	mbrmsk.bits[0] = 0x28; /*port3, port5*/
	untagmsk.bits[0] = 0x28;
	fid = 3;
	rtk_vlan_set(vid3, mbrmsk, untagmsk, fid, ulfid, vbfwd);
	/*set PVID for each port*/
	port = 0;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	port = 1;
	rtk_vlan_portPvid_set(port, vid2, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	port = 2;
	rtk_vlan_portPvid_set(port, vid2, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	port = 3;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	port = 5;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	port = 6;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
}

int dfsgw_904x_emc_test_dut_config()
{
	rtk_api_ret_t retVal;
	rtk_port_t port;
	rtk_vlan_t vid1,vid2,vid3;
    rtk_portmask_t mbrmsk;
    rtk_portmask_t untagmsk;
    rtk_fid_t fid1,fid2,fid3;
    rtk_vlan_ivlsvl_t ulfid = VLAN_IVL;
    rtk_vlan_fwdmode_t vbfwd = ALE_BASED_FWD;
    rtk_pri_t priority = 0;
    rtk_vlan_acceptFrameType_t accept_frame_type = ACCEPT_FRAME_TYPE_ALL;
    rtk_vlan_txTagStatus_t tag_status = TAG_STATUS_WITHOUT_TAG;
    uint8 phymask;
    rtk_enable_t stpAbility = ENABLED;
    rtk_stp_type_t stpType = STP_TYPE_RSTP;

 	/*set p0-p3 phy as master*/
    phymask = 0x1f;
    phy_rolecfg_set(phymask, 1);
    phy_reset(0x01);
    phy_reset(0x02);
    phy_reset(0x04);
    phy_reset(0x08);
    phy_reset(0x10);
	/*initialize VLAN*/
	rtk_vlan_init();
	rtk_stp_ability_set(stpAbility);
	rtk_stp_type_set(stpType);
	/*all the ports are in the default vlan 1 after VLAN is initialized.
	Modify it as follows:
	VLAN1 member:port4[C0], port5[E0], port6[E1];
	VLAN2 member:port0, port1;
	VLAN3 member:port2, port3;
	*/
	vid1 = 10;
	vid2 = 20;
	vid3 = 30;
	fid1 = 1;
	fid2 = 2;
	fid3 = 3;

	mbrmsk.bits[0] = 0x70; /*port4[C0], port5[E0], port6[E1]*/
	untagmsk.bits[0] = 0x70;
	rtk_vlan_set(vid1, mbrmsk, untagmsk, fid1, ulfid, vbfwd);
	mbrmsk.bits[0] = 0x03; /*port0, port1*/
	untagmsk.bits[0] = 0x03;
	rtk_vlan_set(vid2, mbrmsk, untagmsk, fid2, ulfid, vbfwd);
	mbrmsk.bits[0] = 0x0C; /*port2, port3*/
	untagmsk.bits[0] = 0x0C;
	rtk_vlan_set(vid3, mbrmsk, untagmsk, fid3, ulfid, vbfwd);
	/*clear member set and untag set for default VLAN1*/
	mbrmsk.bits[0] = 0x0;
	untagmsk.bits[0] = 0x0;
	rtk_vlan_set(1, mbrmsk, untagmsk, 0, ulfid, vbfwd);
	/*set PVID for each port*/
	port = 0;
	rtk_vlan_portPvid_set(port, vid2, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid2, port, STP_FORWARDING);
	port = 1;
	rtk_vlan_portPvid_set(port, vid2, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid2, port, STP_FORWARDING);
	port = 2;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid3, port, STP_FORWARDING);
	port = 3;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid3, port, STP_FORWARDING);
	port = 4;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid1, port, STP_FORWARDING);
	port = 5;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid1, port, STP_FORWARDING);
	port = 6;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid1, port, STP_FORWARDING);
}

int dfsgw_904x_emc_test_partner_config()
{
	rtk_api_ret_t retVal;
	rtk_port_t port;
	rtk_vlan_t vid1,vid2,vid3;
    rtk_portmask_t mbrmsk;
    rtk_portmask_t untagmsk;
    rtk_fid_t fid1,fid2,fid3;
    rtk_vlan_ivlsvl_t ulfid = VLAN_IVL;
    rtk_vlan_fwdmode_t vbfwd = ALE_BASED_FWD;
    rtk_pri_t priority = 0;
    rtk_vlan_acceptFrameType_t accept_frame_type = ACCEPT_FRAME_TYPE_ALL;
    rtk_vlan_txTagStatus_t tag_status = TAG_STATUS_WITHOUT_TAG;
    uint8 phymask;
    rtk_enable_t stpAbility = ENABLED;
    rtk_stp_type_t stpType = STP_TYPE_RSTP;

	/*set p0-p3 phy as slave*/
    phymask = 0x1f;
    phy_rolecfg_set(phymask, 0);
    phy_reset(0x01);
    phy_reset(0x02);
    phy_reset(0x04);
    phy_reset(0x08);
    phy_reset(0x10);
	/*initialize VLAN*/
	rtk_vlan_init();
	rtk_stp_ability_set(stpAbility);
	rtk_stp_type_set(stpType);
	/*all the ports are in the default vlan 1 after VLAN is initialized.
	Modify it as follows:
	VLAN1 member:port4[C0], port0;
	VLAN2 member:port1, port2;
	VLAN3 member:port3, port5[E0], port6[E1];
	*/
	vid1 = 10;
	vid2 = 20;
	vid3 = 30;
	fid1 = 1;
	fid2 = 2;
	fid3 = 3;

	mbrmsk.bits[0] = 0x11; /*port4[C0], port0*/
	untagmsk.bits[0] = 0x11;
	rtk_vlan_set(vid1, mbrmsk, untagmsk, fid1, ulfid, vbfwd);
	mbrmsk.bits[0] = 0x06; /*port1, port2*/
	untagmsk.bits[0] = 0x06;
	rtk_vlan_set(vid2, mbrmsk, untagmsk, fid2, ulfid, vbfwd);
	mbrmsk.bits[0] = 0x68; /*port3, port5[E0], port6[E1]*/
	untagmsk.bits[0] = 0x68;
	rtk_vlan_set(vid3, mbrmsk, untagmsk, fid3, ulfid, vbfwd);
	/*clear member set and untag set for default VLAN1*/
	mbrmsk.bits[0] = 0x0;
	untagmsk.bits[0] = 0x0;
	rtk_vlan_set(1, mbrmsk, untagmsk, 0, ulfid, vbfwd);
	/*set PVID for each port*/
	port = 0;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid1, port, STP_FORWARDING);
	port = 1;
	rtk_vlan_portPvid_set(port, vid2, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid2, port, STP_FORWARDING);
	port = 2;
	rtk_vlan_portPvid_set(port, vid2, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid2, port, STP_FORWARDING);
	port = 3;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid3, port, STP_FORWARDING);
	port = 4;
	rtk_vlan_portPvid_set(port, vid1, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid1, port, STP_FORWARDING);
	port = 5;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid3, port, STP_FORWARDING);
	port = 6;
	rtk_vlan_portPvid_set(port, vid3, priority);
	rtk_vlan_portAcceptFrameType_set(port, accept_frame_type);
	rtk_vlan_portEgressTagStatus_set(port, tag_status);
	rtk_stp_mstpState_set(fid3, port, STP_FORWARDING);
}

